package cn.com.mfish.scheduler.common;


import cn.com.mfish.scheduler.execute.DisallowConcurrentJobExecute;
import cn.com.mfish.scheduler.execute.GeneralJobExecute;
import cn.com.mfish.scheduler.entity.Job;
import cn.com.mfish.scheduler.entity.JobMeta;
import com.alibaba.fastjson2.JSON;
import org.quartz.*;
import org.springframework.scheduling.quartz.QuartzJobBean;

import java.text.MessageFormat;
import java.util.HashMap;
import java.util.Map;

/**
 * @description: 任务公共类
 * @author: mfish
 * @date: 2023/2/6 15:43
 */
public class JobUtils {
    //job参数标签
    public static final String JOB_DATA_MAP = "job_data_map";

    /**
     * 获取任务key
     * <p>
     * 根据提供的JobMeta对象，构建并返回一个JobKey实例该JobKey实例唯一标识了一个任务
     * </p>
     *
     * @param jobMeta 任务元数据，包含了构建JobKey所需的信息，如任务名和任务组
     * @return 返回根据jobMeta参数构建的JobKey实例
     */
    public static JobKey getJobKey(JobMeta jobMeta) {
        return JobKey.jobKey(jobMeta.getName(), jobMeta.getGroup());
    }

    /**
     * 创建任务
     *
     * @param scheduler Scheduler实例，用于操作任务调度
     * @param jobMeta   任务元数据，包含任务的各种配置信息
     * @param cover     是否覆盖现有任务的标志
     * @throws SchedulerException 如果调度操作失败
     */
    public static void createJob(Scheduler scheduler, JobMeta jobMeta, boolean cover) throws SchedulerException {
        // 设置jobKey
        JobKey jobKey = new JobKey(jobMeta.getName(), jobMeta.getGroup());
        //判断job是否存在
        if (scheduler.checkExists(jobKey) && !cover) {
            throw new SchedulerException("job key : " + jobKey + "已存在!");
        }
        // 获得jobDataMap
        JobDataMap jobDataMap = buildJobDataMap(jobMeta);
        //实例化作业
        JobDetail jobDetail = JobBuilder.newJob(JobUtils.getJobClass(jobMeta.isAllowConcurrent()))
                .withIdentity(jobKey).withDescription(jobMeta.getDescription())
                .requestRecovery(jobMeta.getRecovery())
                .storeDurably(jobMeta.getDurability()).setJobData(jobDataMap).build();
        // 添加job
        scheduler.addJob(jobDetail, true, !jobMeta.getDurability());
    }

    public static JobDataMap buildJobDataMap(JobMeta jobMeta) {
        // 获得jobDataMap
        JobDataMap jobDataMap = new JobDataMap();
        if (jobMeta.getDataMap() != null && !jobMeta.getDataMap().isEmpty()) {
            jobDataMap.putAll(jobMeta.getDataMap());
        }
        return jobDataMap;
    }

    /**
     * 获取任务执行类
     * <p>
     * 根据是否允许并发，返回不同的任务执行类。如果允许并发，返回GeneralJobExecute.class；
     * 如果不允许并发，返回DisallowConcurrentJobExecute.class。这种设计是为了在任务执行时，
     * 能够根据任务的并发需求，选择合适的执行类，以确保任务的正确执行。
     *
     * @param allowConcurrent 是否允许并发执行
     * @return 返回对应的任务执行类
     */
    public static Class<? extends QuartzJobBean> getJobClass(boolean allowConcurrent) {
        return allowConcurrent ? GeneralJobExecute.class : DisallowConcurrentJobExecute.class;
    }

    /**
     * 构建任务元数据
     *
     * @param job 任务
     * @return 任务元数据，包含任务的各种配置信息
     */
    public static JobMeta buildJobDetailMeta(Job job) {
        JobMeta jobDetailMeta = new JobMeta();
        jobDetailMeta.setName(MessageFormat.format("{0}:[{1}]", job.getJobName(), job.getId()));
        jobDetailMeta.setGroup(job.getJobGroup());
        jobDetailMeta.setDescription(job.getRemark());
        jobDetailMeta.setAllowConcurrent(1 == job.getAllowConcurrent());
        Map<String, Object> map = new HashMap<>();
        map.put(JOB_DATA_MAP, JSON.toJSONString(job));
        jobDetailMeta.setDataMap(map);
        return jobDetailMeta;
    }
}
